package com.lsk.mps.backend.service.impl;

import com.google.gson.Gson;
import com.lsk.mps.backend.aspect.annotation.Cached;
import com.lsk.mps.backend.mapper.MessageConfirmMapper;
import com.lsk.mps.backend.mapper.MessageMapper;
import com.lsk.mps.backend.mapper.UserMapper;
import com.lsk.mps.backend.model.Message;
import com.lsk.mps.backend.model.MessageConfirm;
import com.lsk.mps.backend.model.User;
import com.lsk.mps.backend.redis.RedisDao;
import com.lsk.mps.backend.service.MessageService;
import com.lsk.mps.backend.util.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service("messageService")
public class MessageServiceImpl implements MessageService {
    @Autowired
    private MessageMapper messageMapper;
    @Autowired
    private MessageConfirmMapper messageConfirmMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private Gson gson;
    @Autowired
    private RedisDao redisDao;

    private static final int ITEMS_PER_PAGE = 10;

    @Override
    public void publishMessage(String title, String content, String type, Boolean needConfirm) {
        Message message = new Message();
        message.setContent(content);
        message.setTitle(title);
        message.setNeedConfirm(needConfirm);
        message.setType(type);
        message.setPublishDate(new Date());
        messageMapper.addMessage(message);
        String messageJson = gson.toJson(message);
        redisDao.publish("message", messageJson);
    }


    @Override
    public void confirmMessage(Integer targetID, String content) {
        Integer uid = SecurityUtil.currentUID();
        MessageConfirm messageConfirm = new MessageConfirm();
        messageConfirm.setContent(content);
        messageConfirm.setTargetMessage(targetID);
        messageConfirm.setConfirmer(uid);
        messageConfirm.setConfirmDate(new Date());
        messageConfirmMapper.addMessageConfirm(messageConfirm);
        redisDao.publish("message_confirm", gson.toJson(messageConfirm));
    }

    @Override
    public List<Message> allMessages(Integer page) {
        int offset = (page - 1) * ITEMS_PER_PAGE;
        return messageMapper.queryAllMessage(offset, ITEMS_PER_PAGE);
    }

    @Override
    public Integer messagePages() {
        int messageCount = messageMapper.messageCount();
        return (int) Math.ceil(messageCount / ((double) ITEMS_PER_PAGE));
    }

    @Override
    public List<MessageConfirm> queryMessageConfirms(Integer targetID, Integer page) {
        int offset = (page - 1) * ITEMS_PER_PAGE;
        return messageConfirmMapper.queryConfirms(targetID, offset, ITEMS_PER_PAGE);
    }

    @Override
    public Integer messageConfirmsPages(Integer targetID) {
        int messageConfirmCount = messageConfirmMapper.confirmCount(targetID);
        return (int) Math.ceil(messageConfirmCount / ((double) messageConfirmCount));
    }

    @Override
    public List<User> notConfirmedUsers(Integer targetID) {
        if (redisDao.exists("CACHE-notConfirmedUsers-" + targetID.toString())) {
            return gson.fromJson(redisDao.get("CACHE-notConfirmedUsers-" + targetID.toString()), List.class);
        } else {
            List<User> users = userMapper.queryAllUsersNoPaged();
            List<Integer> confirmers = messageConfirmMapper.queryConfirmers(targetID);
            List<User> result = users.stream()
                    .filter(user -> !confirmers.contains(user.getId()))
                    .collect(Collectors.toList());
            redisDao.set("CACHE-notConfirmedUsers-" + targetID.toString(), gson.toJson(result));
            return result;
        }
    }
}
